#include "peripheral.h"
#include "globalDef.h"
#include "watchDog_hw.h"
#include "tim_hw.h"
#include "uart_hw.h"
#include "string.h"
#include "gd32e10x_misc.h"
#include "SPI_Flash.h"
#include "Flash_user.h"
#include "IAP.h"
#include "sleep.h"
#include "CANInit.h"
#include "L610.h"
#include "adc_hw.h"
#include "L610_hw.h"
#include "CarMonitor.h"
#include "OneSecProcess.h"
#include "IO_Ctrl_hw.h"
#include "paraTable.h"
#include "storeCarInf.h"
#include "LED_hw.h"
#include "led.h"
#include "debug_prt.h"
#include "EngineStart.h"


//修改PCU主频时使用下面3项
extern void system_clock_hxtal(void);
extern void system_clock_120m_hxtal(void);
extern uint32_t SystemCoreClock;
printinfo_t prt_inf = {0};

uint8_t	sample_io(void)
{
	return gpio_input_bit_get(GPIOB,GPIO_PIN_1);
}


void initSampleIO(void)
{
	rcu_periph_clock_enable(RCU_GPIOB);
	gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ,GPIO_PIN_1);
}

/*
bit0 = 1,代表看门狗初始化失败
bit1 = 1，Flash初始化失败

*/
uint32_t	selfCheckResult = 0;


/*
初始化SIM硬件IO
*/
void init_SIM_gpio(void)
{
	uint8_t sta = 0;
	/* enable the key clock */
	rcu_periph_clock_enable(RCU_GPIOB); 
	//rcu_periph_clock_enable(RCU_AF);

	//初始化IO为OD输出
	gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_15);
	
	//默认High-esim
	//gpio_bit_set(GPIOB,GPIO_PIN_15);
	//Low-抽屉卡
	//gpio_bit_reset(GPIOB,GPIO_PIN_15);
	if(0 == readSwSIMfromFlash(&sta))
	{
		if(sta == 1)
		{
			#if ((CONFIG_USER_SIM == 0)||(CONFIG_USER_SIM == 2))
			//Low-抽屉卡
			gpio_bit_reset(GPIOB,GPIO_PIN_15);
			#elif (CONFIG_USER_SIM == 1)
			//High-esim
			gpio_bit_set(GPIOB,GPIO_PIN_15);
			#endif
		}
		else
		{
			#if (CONFIG_USER_SIM == 2)
			//Low-抽屉卡
			gpio_bit_reset(GPIOB,GPIO_PIN_15);
			#elif ((CONFIG_USER_SIM == 1) || (CONFIG_USER_SIM == 0))
			//High-esim
			gpio_bit_set(GPIOB,GPIO_PIN_15);	
			#endif
		}
	}
	else
	{
		#if ((CONFIG_USER_SIM == 0)||(CONFIG_USER_SIM == 2))
		//Low-抽屉卡
		gpio_bit_reset(GPIOB,GPIO_PIN_15);
		#elif (CONFIG_USER_SIM == 1)
		//High-esim
		gpio_bit_set(GPIOB,GPIO_PIN_15);
		#endif
	}
}

/*
初始化及自检
开机时先以120M主频初始化
*/
void initPeri(void)
{
	//初始化中断想量表，如果没有IAP，写0
	nvic_vector_table_set(NVIC_VECTTAB_FLASH, 0x08005400);		//use IAP
	//nvic_vector_table_set(NVIC_VECTTAB_FLASH, 0);					//no IAP
	init_SIM_gpio();
	turnOffPLL();
	//初始化指示灯
	init_led_gpio();
	initLED();
	//串口0是调试串口，但是L610可以和PC透传数据
	//串口1与L610通信
	initUart0DMA(115200);
	initUart1DMA(115200);
	#if _En_Debug_Prt
	//打印版本号
	printf("\r\n============================================================================\r\n");
	printf("Version = %02x.%02x.%02x%02x.%02x%02x.%02x%02x%02x\r\n", 
				_def_verson[0],_def_verson[1],_def_verson[2],
				_def_verson[3],_def_verson[4],_def_verson[5],
				_def_verson[6],_def_verson[7],_def_verson[8]);			
	//打印版本编译日期			
	printf("%s,%s\r\n", __DATE__, __TIME__);	//系统函数打印，阻塞
	#endif
	#if WatchdogEnable_def
	//初始化看门狗
	if (initWatchDog() != 0x00)
	{
		setSelfCheckResult(0);
	}
	#endif	//WatchdogEnable_def
	// 车辆监控相关变量
	initParaTable();
	initCarMonitor();
	ReadParaTable();
	//对外IO监控
	init_IOCtrl_hw();
	//adc 初始化
	adc_config(0);
	//初始化
	#if _EN_L610
	initL610Var();
	initL610PowerIO_hw();
#if 1	/*由于系统升级复位后，版本号上报的速度比较快导致L610解析失败需删除增加延时上报机制。2022.04.25 YXX*/
	sendMcuVersion();
#else	
	sendGDVersion2L610();	//主动给L610上报本地版本号
#endif
	#endif
	//获取当前继电器控制状态
	readRelay2Flash();
	//秒时间
	InitTimer1MS();
	#if _EnCAN
#if 1	/*由于CAN电平使能位低电平使能系统复位后对CAN芯片使能无效，
		所以需要增加CAN上电复位机制。系统重启3秒后重启启动CAN芯片。2022.04.25 YXX*/
	rebootCANHardware();	//启动CAN上电复位机制
#else
	InitCANConfig();		
#endif	
	getCarInf();			//提取历史数据覆盖当前车身数据
	#endif

	#if _EnSleep_def
	//初始化完成即可进入休眠
	sleep();	
	#endif

	#if EnableDMA_Test_Def
	//让L610复位，重新发开始测试的数据
	send_general_package_to_uart(0x9530, 0, 0, 0,0, 1);
	delay(1000);
	#endif

	#if CONFIG_USER_RF433 > 0u
	initSampleIO();
	initTimer68uS();
	#endif

	#if def_EngineStart
	initEngS_Var();
	#endif
	getprintinfo_t(&prt_inf);
}


void turnOffCANs(void)
{
	//CAN0
	rcu_periph_clock_enable(RCU_GPIOA);
	gpio_init(GPIOA, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ, GPIO_PIN_8);
	gpio_bit_set(GPIOA,GPIO_PIN_8);//RS：0 work, 1 standby
	//power
	rcu_periph_clock_enable(RCU_GPIOB);
	gpio_init(GPIOB, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ, GPIO_PIN_12);
	//gpio_bit_reset(GPIOB,GPIO_PIN_12);//0 power on; 1 power off
	gpio_bit_set(GPIOB,GPIO_PIN_12);//0 power on; 1 power off

	//CAN1
	rcu_periph_clock_enable(RCU_GPIOB);
	gpio_init(GPIOB, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ, GPIO_PIN_4);
	//gpio_bit_reset(GPIOB,GPIO_PIN_4);	//RS: 0 work, 1 standby
	gpio_bit_set(GPIOB,GPIO_PIN_4);	//RS: 0 work, 1 standby

	//power
	rcu_periph_clock_enable(RCU_GPIOB);
	gpio_init(GPIOB, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ, GPIO_PIN_7);
	//gpio_bit_reset(GPIOB,GPIO_PIN_7);//0 power on; 1 power off
	gpio_bit_set(GPIOB,GPIO_PIN_7);//0 power on; 1 power off
}

void turnOnCANs(void)
{
	InitCANConfig();	
}


/*
设置自检结果位=1
bitX = 0即selfCheckResult的bit0 = 1
bitX = 1即selfCheckResult的bit1 = 1
...
bitX = 31即selfCheckResult的bit31 = 1

bit0: 看门狗初始化失败
bit1: flash 开机自检错误
bit2：L610串口中断接收下标越界


*/
void setSelfCheckResult(uint8_t bitX)
{
	selfCheckResult |= (uint32_t)1<<bitX;
}

/*
获取自检结果
每个位的意思，参考变量定义
*/
uint32_t getSelfCheckResult(void)
{
	return selfCheckResult ;
}

//理论上上层读取自检结果后，需要清所有错误位
void clearAllSysError(void)
{
	selfCheckResult = 0;
}





//进入深度休眠，
//进入条件，电压低于设置值
//激活机制，收到CAN数据或者5秒定时器到时
//之所以定5秒定时器，因为要喂看门狗
//如果电压正常后，或收到CAN数据，则退出休眠，但会重新调用单独初始化函数
//和reInitPeripheral()对应
void goDeepSleep(void)
{

}

//和goDeepSleep()对应
void reInitPeripheral(void)
{
	//串口2是调试串口，但是L610可以和PC透传数据

	initUart1DMA(115200);

	
	
	//对外IO监控
	init_IOCtrl_hw();
		
	//adc 初始化

	adc_config(0);


	
	//初始化
	#if _EN_L610
	initL610PowerIO_hw();
	#endif
	

	initUart0DMA(115200);

	

	#if _EnCAN
	//CAN
	//InitCANConfig();	
	#endif
	
	
	#if _EnSleep_def
	//初始化完成即可进入休眠
	sleep();	
	#endif
}

extern uint32_t SystemCoreClock;

void turnOffPLL(void)
{	
	if (SystemCoreClock == HXTAL_VALUE)
	{
		//关闭内部晶振和PLL
		RCU_CTL &= ~RCU_CTL_IRC8MEN;
		//关闭PLL
		/* disable PLL1 */
		RCU_CTL &= ~RCU_CTL_PLL1EN;
		/* disable PLL */
		RCU_CTL &= ~RCU_CTL_PLLEN;
	}
	
	
	
	//把对外串口2失效了，防止IAP中初始化影响
	
	
	
	
	//先把2路CAN都失效了
	turnOffCANs();
	
	
}


void HigherCANPriority(void)
{
	nvic_irq_enable(CAN0_RX0_IRQn, 0, 0);
	nvic_irq_enable(CAN1_RX1_IRQn, 0, 0);
	
}

void lowerCANsPriority(void)
{
	nvic_irq_enable(CAN0_RX0_IRQn, 1, 0);
	nvic_irq_enable(CAN1_RX1_IRQn, 1, 0);
	
}

void HigherUartPriority(void)
{
	nvic_irq_enable(USART0_IRQn, 0, 0);
}

//重启单片机
void reBootMe(void)
{
	__set_FAULTMASK(1);      // 关闭所有中断
	NVIC_SystemReset();
}

